package com.hourse.platform.service.impl;

import com.hourse.platform.common.ErrorMsg;
import com.hourse.platform.entity.MenuEntity;
import com.hourse.platform.entity.RoleGroupEntity;
import com.hourse.platform.entity.UserEntity;
import com.hourse.platform.exception.AppException;
import com.hourse.platform.service.RoleService;
import com.hourse.platform.service.UserService;
import com.hourse.platform.utils.AppTools;
import com.hourse.platform.utils.SqlParams;
import com.hourse.platform.vo.CreateUserVO;
import com.hourse.platform.vo.RoleVO;
import com.hourse.platform.vo.UpdatePwdReqVo;
import com.hourse.platform.vo.UserListVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Slf4j
@Service
public class UserServiceImpl extends PublicServiceImpl implements UserService {

    @Autowired
    private RoleService roleService;

    /**
     * @param account
     * @param password
     * @功能描述: 【获取用户】
     */
    @Transactional(readOnly = true)
    @Override
    public UserEntity getUser(String account, String password) {

        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" from UserEntity a where a.account = :account");
        sqlParams.append(" and a.password = :password order by a.createTime desc");

        sqlParams.add("account", account);
        sqlParams.add("password", password);

        return (UserEntity) baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());
    }

    @Override
    @Transactional(readOnly = true)
    public UserEntity getUserAccount(String account) {

        SqlParams sqlParams = new SqlParams()
                .append(" from UserEntity a where a.account = :account")
                .add("account", account);

        return (UserEntity) baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());
    }

    /**
     * @param account
     * @功能描述: 【获取用户】
     */
    @Transactional(readOnly = true)
    UserEntity getUser(String account) {

        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" from UserEntity a where a.account = :account");
        sqlParams.add("account", account);

        return (UserEntity) baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());
    }

    /**
     * @功能描述: 【创建用户】
     *
     */
    @Transactional(rollbackFor = AppException.class)
    @Override
    public void createUser(CreateUserVO createUserVO) throws AppException {

        try {

            UserEntity user = getUser(createUserVO.getAccount());

            if (user != null) {
                ErrorMsg.ACCOUNT_ALREADY_EXISTS.Ex();
            }

            UserEntity newUser = new UserEntity();
            newUser.setAccount(createUserVO.getAccount());
            newUser.setName(createUserVO.getName());
            newUser.setPlatform(createUserVO.getPlatform());
            newUser.setCreateTime(new Date());

//            String password = getRandomStr(6, 888);
            String password = createUserVO.getPassword();

            String pass = AppTools.EncryptionPassword(createUserVO.getAccount(), password);
            newUser.setPassword(pass);

            log.info("【创建账号】:{}", createUserVO.getAccount());
            log.info("【生成密码】:{}", password);

            baseDao.saveObject(newUser);

        } catch (Exception e) {
            ErrorMsg.SYSTEM_ERR.Ex();
        }
    }

    /**
     * @功能描述: 【获取用户列表】
     */
    @Transactional(readOnly = true)
    @Override
    public List<UserListVO> getUserList() {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" select new com.hourse.platform.vo.UserListVO(a.id,a.account,a.name,a.createTime,a.platform)")
                .append(" from UserEntity a order by a.createTime desc");
        return baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams());
    }

    /**
     * @功能描述: 【获取用户角色】
     */
    @Transactional(readOnly = true)
    @Override
    public List<RoleVO> getRoleList(String userId) {

        List<RoleVO> roleList = roleService.getRoleGroupList();

        for (RoleVO roleVO : roleList) {
            roleVO.setAuth(isAuth(userId, roleVO.getId()) ? "1" : "0");
        }
        return roleList;
    }

    /**
     * @param userId
     * @param roleId
     * @功能描述: 【删除用户角色】
     */
    @Transactional(rollbackFor = AppException.class)
    @Override
    public void deleteUserRole(String userId, String roleId) throws AppException {
        try {

            SqlParams sqlParams = new SqlParams();
            sqlParams.append(" delete from user_role where user_id = :userId");
            sqlParams.append(" and role_id = :roleId");
            sqlParams.add("userId", userId);
            sqlParams.add("roleId", roleId);

            baseDao.executeSqlUpdate(sqlParams.getSql(), sqlParams.getParams());

        } catch (Exception e) {
            e.printStackTrace();
            ErrorMsg.DB_ERR.Ex();
        }
    }

    @Transactional(readOnly = true)
    Set getAllowIdSet() {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" select DISTINCT(c.menu_id) from role_menu  c where c.role_id in(");
        sqlParams.append(" select DISTINCT e.role_id from user_role b");
        sqlParams.append(" left join  role_group_item e on b.role_id = e.role_group_id ");
        sqlParams.append(" where b.user_id = :userId ) ");

        sqlParams.add("userId", AppTools.GetCurrentUserId());

        List list = baseDao.getItemListByNativeSQL(sqlParams.getSql(), sqlParams.getParams());
        Set set = new HashSet();
        set.addAll(list);
        return set;
    }

    /**
     * @功能描述: 【获取用户菜单】
     * @作 者 : Rain
     * @创建时间 : 2020/12/7 16:52
     */
    @Transactional(readOnly = true)
    @Override
    public List getUserMenuList() {

        Set<String> menuIdSet = getAllowIdSet();

        SqlParams sqlParams = SqlParams.New().append(" from MenuEntity a where a.parentId is null order by a.sort");
        List<MenuEntity> allMenuList = baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams());
        List<MenuEntity> showMenuList = new ArrayList<>();

        for (MenuEntity menu : allMenuList) {
            MenuEntity menuEntity = menuFilter(menuIdSet, menu);
            if (menuEntity != null) {
                showMenuList.add(menuEntity);
            }
        }
        return showMenuList;
    }

    /**
     * @param roleList
     * @功能描述: 【获取有权限的地址】
     */
    @Transactional(readOnly = true)
    @Override
    public List<String> getAllowPaths(List<RoleVO> roleList) {

        List<String> roles = new ArrayList<>();
        for (RoleVO role : roleList) {
            roles.add(role.getId());
        }

        if (roles.size() < 1) {
            return new ArrayList<>();
        }

        return getRoleMenuButtonList(roles);
    }

    @Transactional(readOnly = true)
    List<String> getRoleMenuButtonList(List roleIds) {

        SqlParams sqlParams = new SqlParams()
                .append(" select ")
                .append(" DISTINCT(b.url)")
                .append(" from role_menu_button a ")
                .append(" left join menu_button b on a.menu_button_id = b.id")
                .append(" where a.role_id in(:roleIds)")
                .add("roleIds", roleIds);

        return baseDao.getItemListByNativeSQL(sqlParams.getSql(), sqlParams.getParams());
    }

    public MenuEntity menuFilter(Set<String> allowIds, MenuEntity menu) {

        MenuEntity menuEntity = new MenuEntity();
        if (AppTools.isAdmin() || allowIds.contains(menu.getId())) {

            log.info("=============================================");

            menuEntity.setParentId(menu.getParentId());
            menuEntity.setId(menu.getId());
            menuEntity.setIcon(menu.getIcon());
            menuEntity.setName(menu.getName());
            menuEntity.setUrl(menu.getUrl());
            menuEntity.setComName(menu.getComName());
            menuEntity.setHidden(menu.getHidden());
            menuEntity.setSort(menu.getSort());

            List<MenuEntity> children = new ArrayList();

            for (MenuEntity m : menu.getChildren()) {
                MenuEntity me = menuFilter(allowIds, m);
                if (me != null) {
                    children.add(me);
                }
            }

            menuEntity.setChildren(children);

            return menuEntity;
        } else {
            return null;
        }
    }

    /**
     * @功能描述: 【判断是否拥有该角色】
     */
    @Transactional(readOnly = true)
    boolean isAuth(String userId, String roleId) {
        SqlParams sqlParams = SqlParams.New().append(" from UserRoleEntity a where a.userId = :userId")
                .append(" and a.roleId = :roleId")
                .add("userId", userId).add("roleId", roleId);
        return baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams()).size() > 0;
    }

    @Transactional(rollbackFor = AppException.class)
    @Override
    public void updatePwd(UpdatePwdReqVo vo) throws Exception {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append("update UserEntity a set a.password =:newPassword where a.account = :account and a.password = :oldPassword");
        sqlParams.add("oldPassword", vo.getOldpassword());
        sqlParams.add("account", vo.getAccount());
        sqlParams.add("newPassword", vo.getNewpassword1());
        baseDao.executeUpdate(sqlParams.getSql(), sqlParams.getParams());
    }

    @Transactional(rollbackFor = AppException.class)
    @Override
    public void lostUpdatePwd(String account, String newPassword) throws Exception {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append("update UserEntity a set a.password =:newPassword where a.account = :account");
        sqlParams.add("account", account);
        sqlParams.add("newPassword", newPassword);
        baseDao.executeUpdate(sqlParams.getSql(), sqlParams.getParams());
    }

    @Transactional(readOnly = true)
    @Override
    public RoleGroupEntity getRoleName(String roleId) {
        return (RoleGroupEntity) findById(roleId, RoleGroupEntity.class);
    }

    /**
     * 根据企业id获取当前角色列表
     *
     * @param epId
     * @return
     */
    @Transactional(readOnly = true)
    @Override
    public List<RoleGroupEntity> getRoleGroup(String epId) {

        SqlParams sqlParams = new SqlParams();//RoleGroupEntity

        sqlParams.append("select rg from RoleGroupEntity rg " +
                " left join EnterPriseRoleGroupEntity erg on rg.id = erg.roleGroupId" +
                " where erg.state = '1' and erg.eId =:eId");
        sqlParams.add("eId", epId);

        List<RoleGroupEntity> rgList = baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams());

        if (rgList.size() == 0) {
            sqlParams = new SqlParams();
            sqlParams.append("select rg from RoleGroupEntity rg " +
                    " left join EnterPriseInfoEntity e on rg.id = e.eiRole" +
                    " where e.id =:eId");
            sqlParams.add("eId", epId);
        }

        return baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams());

    }

    @Transactional(readOnly = true)
    @Override
    public List<RoleVO> getRoleListByRoleGroupId(String roleGroupId) {

        SqlParams sqlParams = new SqlParams()
                .append(" select new com.hourse.platform.vo.RoleVO(a.id,a.name,a.code)")
                .append(" from RoleGroupEntity a where a.id = :rgId");
        sqlParams.add("rgId", roleGroupId);

        List<RoleVO> roleList = baseDao.getItemListByNativeHQL(sqlParams.getSql(), sqlParams.getParams());

        for (RoleVO roleVO : roleList) {
            roleVO.setAuth("1");
        }

        return roleList;

    }

    @Override
    @Transactional(readOnly = true)
    public UserEntity getUserById(String userId) throws AppException {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" from UserEntity a where a.id = :id");
        sqlParams.add("id", userId);

        Object entity = baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());

        if (entity == null) {
            log.error("【getUserById】 ========> 根据UserId:{},查询用户信息为空", userId);
            throw new AppException("无对应用户信息");
        }
        return (UserEntity) entity;
    }

    @Override
    @Transactional(readOnly = true)
    public UserEntity getUserByPhone(String phone) throws AppException {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" from UserEntity u where u.account = :account");
        sqlParams.add("account", phone);

        Object entity = baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());

        if (entity == null) {
            log.error("【getUserById】 ========> 根据phone:{},查询用户信息为空", phone);
            throw new AppException("无对应用户信息");
        }
        return (UserEntity) entity;
    }



    /**
     * 根据账号获取用户信息
     *
     * @param phone
     * @return
     */
    @Override
    @Transactional
    public boolean getUserByAccount(String phone) {
        SqlParams sqlParams = new SqlParams();
        sqlParams.append(" from UserEntity a where a.account = :account");
        sqlParams.add("account", phone);

        Object entity = baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());

        if (entity == null) {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 随机产生字符串
     *
     * @param length 字符串长度
     * @param type   类型 (0: 仅数字; 2:仅字符; 别的数字:数字和字符)
     * @return
     */
    public static String getRandomStr(int length, int type) {
        String str = "";
        int beginChar = 'a';
        int endChar = 'z';
        // 只有数字
        if (type == 0) {
            beginChar = 'z' + 1;
            endChar = 'z' + 10;
        }
        // 只有小写字母
        else if (type == 2) {
            beginChar = 'a';
            endChar = 'z';
        }
        // 有数字和字母
        else {
            beginChar = 'a';
            endChar = 'z' + 10;
        }

        // 生成随机类

        Random random = new Random();
        for (int i = 0; i < length; i++) {
            int tmp = (beginChar + random.nextInt(endChar - beginChar));
            // 大于'z'的是数字
            if (tmp > 'z') {
                tmp = '0' + (tmp - 'z');
            }
            str += (char) tmp;
        }

        return str;
    }

    public String getCurtRoleGroupId() {
        return (String) AppTools.getCurrentRoleGroupId();
    }

    @Transactional
    @Override
    public String loadRoleCode(String userId) {//UserRoleEntity
        SqlParams sqlParams = new SqlParams();//RoleGroupEntity
        //UserRoleEntity
        sqlParams.append("select rg.code from UserRoleEntity ur left join RoleGroupEntity rg on rg.id = ur.roleId " +
                " where ur.userId = :userId ");
        sqlParams.add("userId", userId);

        return (String) baseDao.execSingleQuery(sqlParams.getSql(), sqlParams.getParams());

    }

    @Override
    public boolean isAdmin() {

        List<RoleGroupEntity> roles = roleService.getRoles(AppTools.GetCurrentUserId());
        for (RoleGroupEntity role : roles) {
            if (role.getCode().equals("ADMIN_GROUP") || role.getCode().equals("XTGLY")) {
                return true;
            }
        }

        return false;
    }


}
